package cn.stylefeng.mferp.exception;

import cn.stylefeng.mferp.bean.AppResult;
import cn.stylefeng.mferp.bean.ReturnT;
import cn.stylefeng.mferp.modular.system.service.INoticeService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.net.SocketTimeoutException;
import java.sql.SQLException;

/**
 * 异常捕捉
 * controller层异常无法捕获处理，需要自己处理
 * @author yzr
 * created at 2021-03-23
 */
@RestControllerAdvice
@Slf4j
public class DefaultExceptionHandler {

    @Autowired
    private INoticeService noticeService;

    /**
     * 处理其他异常，也是最高级别之一的Exception异常，但全局异常处理会优先处理子类的异常
     *
     * @param e 其他异常信息
     * @return 异常处理结果
     */
    @ExceptionHandler(value = Exception.class)
    public ReturnT<String> handleException(Exception e, HttpServletRequest request) {
        log.error("未知异常！原因是:", e);
        if (StringUtils.isNotBlank(e.getMessage())) {
            noticeService.addExceptionNotice(e);
            return ReturnT.responseFailed(400, e.getMessage());
        }
        return ReturnT.responseFailed(AppResult.RET_COMM_SERVER_ERROR);
    }

    /**
     * 处理参数校验异常(@NotNull等验证)
     *
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ReturnT<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
        String message = e.getMessage();
        if (e.getBindingResult().getFieldError() != null && StringUtils.isNotBlank(e.getBindingResult().getFieldError().getDefaultMessage())) {
            message = e.getBindingResult().getFieldError().getDefaultMessage();
            log.error(e.getBindingResult().getFieldError().getDefaultMessage());
        }
        if (StringUtils.isNotBlank(message)) {
            noticeService.addExceptionNotice(e);
            return ReturnT.responseFailed(400, message);
        }
        return ReturnT.responseFailed(AppResult.RET_COMM_SERVER_ERROR);
    }

    /**
     * 处理参数校验异常
     *
     * @param e 处理参数校验异常
     * @return 异常信息
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ReturnT<String> handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
        log.error("参数异常:{}", e.getMessage());
        noticeService.addExceptionNotice(e);
        return ReturnT.responseFailed(AppResult.RET_COMM_SERVER_ERROR);
    }

    /**
     * 处理空指针的异常
     */
    @ExceptionHandler(value = NullPointerException.class)
    public ReturnT<String> exceptionHandler(NullPointerException e, HttpServletRequest request) {
        log.error("发生空指针异常！原因是:{}", e.getMessage());
        noticeService.addExceptionNotice(e);
        return ReturnT.responseFailed(AppResult.RET_COMM_SERVER_ERROR);
    }

    /**
     * 请求超时
     */
    @ExceptionHandler(value = SocketTimeoutException.class)
    public ReturnT<String> exceptionHandler(SocketTimeoutException e, HttpServletRequest request) {
        log.error("请求超时！原因是:{}", e.getMessage());
        noticeService.addExceptionNotice(e);
        return ReturnT.responseFailed(AppResult.RET_COMM_TIME_OUT);
    }

    /**
     * 请求超时
     */
    @ExceptionHandler(value = SQLException.class)
    public ReturnT<String> exceptionHandler(SQLException e, HttpServletRequest request) {
        log.error("请求超时！原因是: {}", e.getMessage());
        noticeService.addExceptionNotice(e);
        return ReturnT.responseFailed(AppResult.RET_COMM_TIME_OUT);
    }

}
